接續昨天 ngOnDestroy 還沒有記錄完的內容。
這邊有一個蠻特別的事情,就是 ngOnDestroy 只會在該元件所處的網頁還在運行的狀態下才會被啟動。
你可能會覺得沒什麼特別的,阿不就網頁關掉就關掉,還管它什麼元件的 ngOnDestroy 啟不啟動。
你這樣想也是沒錯,
但...... 如果,我們有在該元件的 ngOnDestroy 寫入一些特製的功能(比如: 當該元件進入 ngOnDestroy 時,要直接幫使用者登出的功能),結果使用者直接關掉當下頁面,就會導致元件根本就沒有進入 ngOnDestroy 的 lifecycle,最終,就會導致我們在 ngOnDestroy 撰寫的這些特製的功能沒有被啟動。
那有哪些狀況有可能會造成以上的狀況發生呢?
為了解決以上的狀況,我們必須要引入 Angular 的 HostListener 來監聽網頁的 beforeunload 事件。
首先,什麼是 beforeunload 事件呢?
它是一個當網頁即將要被關閉或重新整理之前,會被觸發的一個事件,當這個事件被觸發的時候,網頁上的資料都還是被保留狀況,也就是使用者還可以反悔的狀況。
接著,我們就用 HostListener 來監聽 beforeunload 被觸發的時候,來執行該元件的 ngOnDestroy 事件,來解決以上的狀況。
我們改寫一下 Day25 的範例
[子元件 -TypeScript]
import { Component, OnDestroy, HostListener} from '@angular/core';
import { AuthService } from '@app/auth.service.ts'
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
export class AppComponent implements OnDestroy {
// ...
@HostListener('window:beforeunload')
ngOnDestroy() {
this.destroy$.next(true)
this.destroy$.unsubscribe()
// ... 使用者登出功能,或是其他特製的功能
}
}
是不是很簡單呢~ 只要利用 HostListener 去監聽 window:beforeunload 的事件,在這行程式碼的下面要接,想要觸發的內容,而以上的範例,我們想要接著觸發的內容就是 ngOnDestroy 囉。
其實,HostListener 有兩個參數,一個是像上面範例所示被監聽的 DOM 事件,第二個參數是這個 DOM 事件的內容,
寫法如下@HostListener('window:beforeunload', ['$event'])
你可能會納悶,為什麼上面的範例你不這樣寫呢?
原因是,ngOnDestroy 是沒有辦法傳入任何參數的喔,如果,我硬將 $event 寫入 ngOnDestroy 的參數部分,會得到以下的錯誤訊息
大概的意思就是無法傳入參數給 ngOnDestroy 。
如果,我們今天希望當使用者離開或重整當下頁面的時候,會跳出一個 alert 提示使用者是否要離開頁面,這個時候,我們可以使用自訂義的函式
寫法如下
[子元件 -TypeScript]
import { Component, OnDestroy, HostListener} from '@angular/core';
import { AuthService } from '@app/auth.service.ts'
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
export class AppComponent implements OnDestroy {
ngOnDestroy() {
this.destroy$.next(true)
this.destroy$.unsubscribe()
}
@HostListener('window:beforeunload', [$event])
onBeforeUnload($event) {
$event.preventDeafult()
$event.returnValue = true
}
}
可以看到我們將 HostListener 的部分改寫在 onBeforeUnload 的上面,而且傳入了 $event ,讓我們可以在 onBeforeUnload 裡面操作裡面的內容。
加入以上的內容之後,當使用者重整或關閉當下頁面都會跳出提示訊息,告知使用者即將要離開頁面了。
但是,要特別注意的是,當我們改以上面的寫法時,該元件的 ngOnDestroy 內容是不會被觸發的喔,因為,beforeunload 被觸發的當下,你的元件都還是可視的(visible),根本還沒有被消除,所以,不會進到 ngOnDestroy 裡面。
來做個總結